package cn.net.isir.utils;

import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.apache.log4j.Logger;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * @author liuxubo
 * @filename QRUtils.java
 * @package cn.net.isir.utils
 * @email lxb@isir.net.cn
 * @date 2018/11/29
 * @comment 二维码工具类
 * @since 1.8
 */
public class QRUtils {

    private static Logger logger = Logger.getLogger(QRUtils.class);

    /**
     * 生成图片，输出到流
     *
     * @param content      要编码的文本内容
     * @param format       图片格式，ImageFormat格式;默认为ImageFormat.png
     * @param outputStream 输出流
     */
    public static void encodeToStream(String content, ImageFormat format, OutputStream outputStream) {
        if (outputStream == null) {
            return;
        }
        if (format == null) {
            format = ImageFormat.png;
        }
        try {
            int width = 300;
            int height = 300;
            //生成图片类型
            Map<EncodeHintType, Object> hints = new HashMap<>();
            //设置字符集
            hints.put(EncodeHintType.CHARACTER_SET, java.nio.charset.StandardCharsets.UTF_8);
            //设置容错等级
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
            //设置边框宽度
            hints.put(EncodeHintType.MARGIN, 2);
            // 生成矩阵
            BitMatrix bitMatrix = new MultiFormatWriter().
                    encode(content, BarcodeFormat.QR_CODE, width, height, hints);
            //输出到流
            MatrixToImageWriter.writeToStream(bitMatrix, format.name(), outputStream);
            logger.info("content: " + content);
            logger.info("encode: " + java.nio.charset.StandardCharsets.UTF_8);
            logger.info("type: " + BarcodeFormat.QR_CODE.name());
            logger.info(123);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /**
     * 从流中读取信息
     *
     * @param inputStream 输入流
     * @return 解码后的信息
     */
    public static String decodeFromStream(InputStream inputStream) throws FileNotFoundException {
        if (inputStream == null) {
            return null;
        }
        try {
            BufferedImage image = ImageIO.read(inputStream);
            LuminanceSource source = new BufferedImageLuminanceSource(image);
            Binarizer binarizer = new HybridBinarizer(source);
            BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);

            Map<DecodeHintType, Object> hints = new HashMap<>();
            hints.put(DecodeHintType.CHARACTER_SET, StandardCharsets.UTF_8);
            Result result = new MultiFormatReader().decode(binaryBitmap, hints);// 对图像进行解码
            logger.info("result: " + result.getText());
            logger.info("encode: " + result.getBarcodeFormat());
            return result.getText();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }


    public static void main(String[] args) throws IOException {
        File file = new File("D://" + System.currentTimeMillis() + ".png");
        encodeToStream("http://www.baidu.com/", ImageFormat.png, new FileOutputStream(file));
        decodeFromStream(new FileInputStream(file));
        logger.info(ImageFormat.bmp.name());
    }

    /**
     * 图片格式枚举
     */
    public enum ImageFormat {
        bmp, clib, gif, jpeg, pcx, png, pnm, raw, tiff, wbmp
    }
}
